/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.webanovare.ruzzle.mgr;

import com.webanovare.ruzzle.mgr.impl.ActiveGame;
import com.webanovare.ruzzle.mgr.impl.GameState;
import com.webanovare.ruzzle.mgr.impl.IGame;
import com.webanovare.ruzzle.mgr.impl.IHandleState;
import com.webanovare.ruzzle.mgr.impl.OpenGame;
import com.webanovare.ruzzle.misc.Player;
import com.webanovare.ruzzle.misc.TimeSetting;
import com.webanovare.ruzzle.misc.Trie;
import java.awt.Point;
import java.util.List;
import java.util.Map;

/**
 * Handles a game between two players. It contains the game settings and 
 * forwards information to the corresponding state (either Open or Active) 
 * it's in. Uses the state pattern.
 */
public class Game implements IHandleState, IGame {
    private Player owner;
    private Player opponent;
    private GameState state;
    private int size;
    private TimeSetting time;
    private int gameId;
    private String language;
    
    public static IGame createInstance(Player owner, int size, TimeSetting time, int gameId, String language) {
        return new Game(owner, size, time, gameId, language);
    }
    
    private Game(Player owner, int size, TimeSetting time, int gameId, String language) {
        this.state = new OpenGame(this);
        this.owner = owner;
        this.size = size;
        this.time = time;
        this.gameId = gameId;
        this.language = language;
    }
    
    @Override
    public Player getOpponent() {
        return this.opponent;
    }
    
    @Override
    public Player getOwner() {
        return this.owner;
    }
    
    @Override
    public void changeToActive() {
        this.state = new ActiveGame(this, this.language);
    }

    @Override
    public int getSize() {
        return this.size;
    }

    @Override
    public void setOpponent(Player p) {
        if(this.opponent == null) {
            this.opponent = p;
        }
    }

    @Override
    public void removeOpponent() {
        this.opponent = null;
    }
    
    @Override
    public Trie getTrie() {
        return this.state.getTrie();
    }
    
    @Override
    public TimeSetting getTimeSettings() {
        return this.time;
    }

    @Override
    public List<Character> getBoard() {
        return this.state.getBoard();
    }
    
    @Override
    public Character[][] getBoardMatrix() {
        return this.state.getBoardMatrix();
    }

    @Override
    public boolean addWord(List<Point> ps, Player p) {
        if(this.isStateActiveGame()) {
            boolean opponent = this.opponent.equals(p);
            return this.state.addWord(ps, opponent);
        }
        return false;
    }

    @Override
    public int getOpponentPoints() {
        if(this.isStateActiveGame()) {
            return this.state.getOpponentPoints();
        }
        return -1;
    }

    @Override
    public int getOwnerPoints() {
        if(this.isStateActiveGame()) {
            return this.state.getOwnerPoints();
        }
        return -1;
    }
    
    @Override
    public int getPoints(Player p) {
        boolean opp = this.opponent.equals(p);
        
        return opp ? this.state.getOpponentPoints() : this.state.getOwnerPoints();
    }
    
    private boolean isStateActiveGame() {
        return this.state instanceof ActiveGame;
    }

    @Override
    public int getGameId() {
        return this.gameId;
    }

    @Override
    public void challenge(Player opponent) {
        this.state.challenge(opponent);
    }

    @Override
    public void accept() {
        this.state.accept();
    }

    @Override
    public void decline() {
        this.state.decline();
    }

    @Override
    public Map<String, Integer> getOwnerStatistics() {
        if(this.isStateActiveGame()) {
            return this.state.getOwnerStatistics();
        }
        return null;
    }

    @Override
    public Map<String, Integer> getOpponentStatistics() {
        if(this.isStateActiveGame()) {
            return this.state.getOpponentStatistics();
        }
        return null;
    }
    
    @Override
    public boolean isActive() {
        return this.isStateActiveGame();
    }
}
